home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / graphics / gnuplot / contrib / campbell / gplotlib.2 < prev    next >
Encoding:
Internet Message Format  |  1992-04-27  |  34.9 KB

  1. From jdc@naucse.cse.nau.edu Thu Mar  5 09:26:50 1992
  2. Return-Path: <jdc@naucse.cse.nau.edu>
  3. Received: from naucse.cse.nau.edu by ra-next.arc.nasa.gov (NeXT-1.0 (From Sendmail 5.52)/NeXT-1.0)
  4.     id AA10628; Thu, 5 Mar 92 09:26:36 PST
  5. Received: by naucse.cse.nau.edu (5.65c/1.5-nau)
  6.     id AA21531; Thu, 5 Mar 1992 10:32:28 -0700
  7. Message-Id: <199203051732.AA21531@naucse.cse.nau.edu>
  8. From: jdc@naucse.cse.nau.edu (John Campbell)
  9. Date: Thu, 5 Mar 1992 10:32:27 MST
  10. X-Mailer: Mail User's Shell (7.2.3 5/22/91)
  11. To: woo@ra-next.arc.nasa.gov
  12. Subject: gplotlib.shr3
  13. Status: R
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then unpack
  17. # it by saving it into a file and typing "sh file".  To overwrite existing
  18. # files, type "sh file -c".  You can also feed this as standard input via
  19. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  20. # will see the following message at the end:
  21. #        "End of archive 3 (of 5)."
  22. # Contents:  cpr.c2
  23. # Wrapped by jdc@naucse.cse.nau.edu on Tue Feb 11 08:42:15 1992
  24. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  25. if test -f 'cpr.c2' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'cpr.c2'\"
  27. else
  28. echo shar: Extracting \"'cpr.c2'\" \(32782 characters\)
  29. sed "s/^X//" >'cpr.c2' <<'END_OF_FILE'
  30. X
  31. Xchar *
  32. XEndString(p)
  33. Xregister char *p;
  34. X{
  35. X   register char c;
  36. X
  37. X   /*
  38. X         * Always return pointer to last non-null char looked at.
  39. X         */
  40. X   while( c = *p++ )
  41. X      if( c == '\\' && *p )
  42. X      {
  43. X         ++p;
  44. X         continue;
  45. X      }
  46. X      else if( c == '"' )
  47. X      {
  48. X         InString = 0;
  49. X         return(p-1);
  50. X      }
  51. X   return(p-2);
  52. X}
  53. X
  54. XNewFunction()
  55. X{
  56. X   register int i;
  57. X
  58. X   if( Space_to_leave <= 0 || !SawFunction ) return;
  59. X   if( LineNumber + Space_to_leave > (PageLength * PagePart /16) )
  60. X      NewPage();
  61. X   else {
  62. X      for( i=0; i < (Space_to_leave); ++i ) PutString("", -1, 0, 1);
  63. X      LineNumber += Space_to_leave;
  64. X   }
  65. X
  66. X   SawFunction = 0;
  67. X}
  68. X
  69. X#define HEADER_SIZE 3
  70. X
  71. XNewPage()
  72. X{
  73. X   ActualPageCount++;
  74. X   ++PageNumber;
  75. X
  76. X   switch( Printer ) {
  77. X      case POSTSCRIPT:
  78. X     puts( "endpage" );
  79. X     PutHeader();
  80. X     puts( "startpage" );
  81. X     break;
  82. X
  83. X      default:
  84. X     putchar('\f');
  85. X     PutHeader();
  86. X     break;
  87. X   }
  88. X   LineNumber = 0;
  89. X}
  90. X
  91. X
  92. XBlankPage()
  93. X{
  94. X   ActualPageCount++;
  95. X   switch( Printer ) {
  96. X      case POSTSCRIPT:
  97. X     break;
  98. X
  99. X      default:
  100. X     if( LineNumber == 0 ) printf( "   " );
  101. X     putchar('\f');
  102. X     break;
  103. X   }
  104. X   LineNumber = 0;
  105. X}
  106. X
  107. X
  108. XPutHeader()
  109. X{
  110. X   register int l, j;
  111. X   char *lname=Title;
  112. X
  113. X   switch( Printer ) {
  114. X      case POSTSCRIPT:
  115. X     printf( "/pagenum %d def\n", PageNumber );
  116. X     break;
  117. X
  118. X      default:
  119. X     if( lname == NULL ) break;
  120. X     putchar('\n');
  121. X     ++LineNumber;
  122. X
  123. X     l = strlen(lname);
  124. X     printf( "%s", FileDate );
  125. X     j = strlen(FileDate);
  126. X     j = GoToColumn(j, 40-(l/2) );
  127. X
  128. X     PutBold(lname, -1, 0);
  129. X     GoToColumn(j+l, 70);
  130. X     printf("Page:%4d\n\n", PageNumber);
  131. X     ++LineNumber;
  132. X     ++LineNumber;
  133. X     break;
  134. X   }
  135. X}
  136. X
  137. XGoToColumn(from, to)
  138. Xregister int from, to;
  139. X{
  140. X   if( from < to)
  141. X   {
  142. X      for( ; from < to; from++ )
  143. X         putchar(' ');
  144. X   }
  145. X   return( to );
  146. X}
  147. X
  148. X#define isidchr(c)      (isalnum(c) || (c == '_'))
  149. X
  150. X/* This used to incorrectly identify a declaration such as
  151. X *     int (*name[])() = { initializers ... }
  152. X * as a function.  It also picked up this in an assembler file:
  153. X *     #define MACRO(x) stuff
  154. X *     MACRO(x):
  155. X * Fixed both of these.   -IAN!
  156. X */
  157. XLooksLikeFunction(s)
  158. Xregister char *s;
  159. X{
  160. X   register char *p;
  161. X   register int i;
  162. X   char *save;
  163. X
  164. X/* By default this routine does 'C', other languages, other routines. */
  165. X   switch (Language) {
  166. X      case FORTRAN:    return LooksLikeFortran(s);
  167. X      case ICON:       return LooksLikeIcon(s);
  168. X      case LISP:       return LooksLikeLisp(s);
  169. X   }
  170. X
  171. X   if( InComment || InString ) return(0);
  172. X
  173. X   save = s;
  174. X
  175. X   i = 0;
  176. X   do
  177. X      {
  178. X      p = FunctionName;
  179. X
  180. X      while( *s && (*s == ' ') || (*s == '\t') ) ++s;
  181. X      if( *s == '*' ) ++s;
  182. X      if( *s && (*s == ' ') || (*s == '\t') ) continue;
  183. X      if( !*s || ((*s != '_') && !isalpha(*s)) ) return(0);
  184. X
  185. X   /* Store this guess into FunctionName. */
  186. X      while( isidchr(*s) )
  187. X         *p++ = *s++;
  188. X      *p = '\0';
  189. X
  190. X      while( *s && (*s == ' ') || (*s == '\t') ) ++s;
  191. X      i++;
  192. X   }
  193. X   while ( *s && *s != '(' && i < 4 );
  194. X
  195. X   if( *s != '(' || *(s+1) == '*' ) return(0);
  196. X
  197. X   for (i = 0; *s; s++)
  198. X   {
  199. X      switch( *s )
  200. X      {
  201. X      case '(':
  202. X         ++i;
  203. X         continue;
  204. X
  205. X      case ')':
  206. X         --i;
  207. X         break;
  208. X
  209. X      default:
  210. X         break;
  211. X      }
  212. X      if( i == 0 ) break;
  213. X   }
  214. X   if( !*s ) return(0);
  215. X
  216. X   while( *s )
  217. X   {
  218. X      if( *s == '{') break;
  219. X      if( *s == ';' || *s == ':' ) return(0);
  220. X      ++s;
  221. X   }
  222. X   /* Don't match macro definitions (terminated with \) */
  223. X   if (s > save + 3 && (*(s-2) == '\\' ||
  224. X                 (*s == '{' && save[strlen(save)-2] == '\\')))
  225. X       return 0;
  226. X   /*
  227. X      This finds the function name (again) and causes it to be bolded.
  228. X      Note that this assumes the name and opening parentheses are on the
  229. X      same line...  (Note also that FunctionName and what we find here are
  230. X      done by two different mechanisms, why?  JDC)
  231. X   */
  232. X   if (p = strchr( save, '(' ) ) {
  233. X      p--;
  234. X      while (p != save && (*p == ' ' || *p == '\t')) --p;
  235. X      for (i=1; p != save && isidchr(*p); i++) p--;
  236. X
  237. X   /* p now points to a string that is 'i' long that needs to be bolded. */
  238. X      if (p > save)
  239. X         PutString (save, p-save, NumberFlag, 0);
  240. X      PutBold (p, i, 1);
  241. X      p += i;
  242. X      PutString (p, -1, 0, 1);
  243. X   }
  244. X   else
  245. X      PutString (save, -1, NumberFlag, 1);
  246. X
  247. X   SawFunction = 1;
  248. X   return(1);
  249. X}
  250. X
  251. X
  252. Xint LooksLikeFortran(str)
  253. Xchar *str;
  254. X{
  255. X   register char *p, *s=str;
  256. X   register int i;
  257. X   char *save;
  258. X   int  offset = 0;
  259. X
  260. X/* Ignore comment or labeled lines (and be stupid about strings) */
  261. X   if (*s != ' ' && *s != '\t') return(0);
  262. X
  263. X   save = s;
  264. X
  265. X   i = 0;
  266. X/*
  267. X      Fortran is easier than 'C', just check if the first word is
  268. X      SUBROUTINE, FUNCTION or PROGRAM (for those who use this on some systems)
  269. X*/
  270. X   while (*s == ' ' || *s == '\t') ++s;  /* Skip white space */
  271. X
  272. X/* SUBROUTINE, FUNCTION, or PROGRAM lines must start with S, F, or P */
  273. X
  274. X   switch (*s) {
  275. X   case 's':
  276. X   case 'S':
  277. X      offset = Compare (s, "SUBROUTINE");
  278. X   break;
  279. X   case 'F':
  280. X   case 'f':
  281. X      offset = Compare (s, "FUNCTION");
  282. X   break;
  283. X   case 'P':
  284. X   case 'p':
  285. X      offset = Compare (s, "PROGRAM");
  286. X   break;
  287. X   }
  288. X   if (offset == 0) {
  289. X   /*
  290. X      Still a chance that this line is INTEGER FUNCTION or some such.
  291. X      (Second Word is "FUNCTION", No legal keyword or type contains
  292. X      an "F", thank goodness.)
  293. X   */
  294. X      while (*s && *s != 'F' && *s != 'f' && *s != '"') ++s;
  295. X      if (!*s)
  296. X         return 0;
  297. X      offset = Compare (s, "FUNCTION");
  298. X      if (!offset)
  299. X         return 0;
  300. X   }
  301. X   p = s + offset;
  302. X
  303. X   /* p now points to a string that is the subroutine or function name. */
  304. X   for (i=0; isidchr(p[i]); ++i)
  305. X      FunctionName[i] = p[i];
  306. X   FunctionName[i] = '\0';
  307. X
  308. X   /* i is the length of the function name that needs to be bolded. */
  309. X   if (p > save)
  310. X      PutString (save, p-save, NumberFlag, 0);
  311. X   PutBold (p, i, 1);
  312. X   PutString (p+i, -1, NumberFlag, 1);
  313. X
  314. X   SawFunction = 1;
  315. X   Braces = 1;  /* Indicate we are in the scope of a routine (inside). */
  316. X   return(1);
  317. X}
  318. X
  319. X
  320. Xint LooksLikeIcon(str)
  321. Xchar *str;
  322. X{
  323. X   register char *p, *s=str;
  324. X   register int i;
  325. X   char *save;
  326. X
  327. X   save = s;
  328. X   i    = 0;
  329. X
  330. X/* For Icon, just check if the first word is ``procedure'' */
  331. X   while (*s == ' ' || *s == '\t') ++s;  /* Skip white space */
  332. X
  333. X   if (s[0] != 'p' || strncmp (s, "procedure", 9) != 0)
  334. X      return 0;
  335. X
  336. X   p = s + 9;  /* Point to character after ``procedure'' */
  337. X   while (*p == ' ' || *p == '\t') ++p;  /* Skip white space */
  338. X
  339. X/* p now points to a string that is the procedure name. */
  340. X   for (i=0; isidchr(p[i]); ++i)
  341. X      FunctionName[i] = p[i];
  342. X   FunctionName[i] = '\0';
  343. X
  344. X/* i is the length of the procedure name that needs to be bolded. */
  345. X   if (p > save)
  346. X      PutString (save, p-save, NumberFlag, 0);
  347. X   PutBold (p, i, 1);
  348. X   PutString (p+i, -1, NumberFlag, 1);
  349. X
  350. X   SawFunction = 1;
  351. X   Braces = 1;  /* Indicate we are in the scope of a routine (inside). */
  352. X   return(1);
  353. X}
  354. X
  355. Xint LooksLikeLisp(str)
  356. Xchar *str;
  357. X{
  358. X#define MAXLDEPTH 32
  359. X   register char *p, *s = str;
  360. X   register int i;
  361. X   char *fend;
  362. X   static int plevel = 0, fcount = -1, flevel[MAXLDEPTH], endseen = 0;
  363. X   int  offset = 0, fseen = 0;
  364. X/*
  365. X   Lisp is a little harder than some others (perhaps indicating we should
  366. X   rework the whole program...)  In order to handle nested definitions and
  367. X   definitions appearing on the same line we need to restrict scanning of
  368. X   input (in order to preserve state information) to one routine.  Hence,
  369. X   Scan() is not used for Lisp and this routine needs to remember that
  370. X   return (1) implies line was printed and AddToTableOfContents() will
  371. X   be called while return (0) implies line will be printed.
  372. X
  373. X   We also have to call NewFunction ourselves (and after the line closing
  374. X   the function definition has been printed).
  375. X*/
  376. X
  377. X   if (endseen) {
  378. X      NewFunction ();
  379. X      endseen = 0;
  380. X   }
  381. X
  382. X   for (fend = s; *s != '\n'; ++s) {
  383. X      switch (*s) {
  384. X      case ';':    /* Rest of line is a comment. */
  385. X         goto comment_seen;  /* So I used a goto, shoot me. */
  386. X      case '/':    /* Maybe... */
  387. X         if (s[1] == '/') goto comment_seen;
  388. X      case '(':
  389. X      case '[':
  390. X         ++plevel;
  391. X      break;
  392. X      case ')':
  393. X         if (fcount >= 0 && plevel == flevel[fcount]) {
  394. X            if (--fcount < 0) fcount = -1;
  395. X            endseen = 1;
  396. X         }
  397. X         --plevel;
  398. X      break;
  399. X      case ']':
  400. X         if (fcount >= 0) {
  401. X            if (--fcount < 0)  {
  402. X               fcount = -1;
  403. X               plevel = 0;
  404. X            }
  405. X            else
  406. X               plevel = flevel[fcount];
  407. X         }
  408. X         endseen = 1;
  409. X      break;
  410. X      case 'D':
  411. X      case 'd':
  412. X         if (offset = Compare (s, "DEFUN")) {
  413. X            if (fseen) {
  414. X            /* Take care of the other function we found on this line. */
  415. X               AddToTableOfContents(NEWFUNCTION);
  416. X            }
  417. X            p = s + offset;
  418. X         /*
  419. X            Be pretty lax about lisp identifiers (as opposed to 'C').
  420. X            This doesn't look safe, but \n is a space character.
  421. X         */
  422. X            for (i = 0; !isspace(p[i]) && p[i] != '('; ++i)
  423. X               FunctionName[i] = p[i];
  424. X            FunctionName[i] = '\0';
  425. X            if (p > fend)
  426. X               PutString (fend, p-fend, NumberFlag, 0);  /* Front part. */
  427. X            PutBold (p, i, 1);
  428. X            fend = p+i;
  429. X            if (++fcount > MAXLDEPTH) {
  430. X               fprintf (stderr, "Function defuns nested too deep\n");
  431. X               --fcount;
  432. X            }
  433. X            flevel[fcount] = plevel;
  434. X            fseen = 1;
  435. X         }
  436. X      break;
  437. X      }  /* switch */
  438. X   }  /* while */
  439. X
  440. Xcomment_seen:
  441. X   if (fseen) {
  442. X      PutString (fend, -1, NumberFlag, 1);  /* End of string part. */
  443. X      SawFunction = 1;
  444. X      return 1;
  445. X   }
  446. X   return 0;
  447. X}
  448. X
  449. X
  450. Xstatic int Compare (str, key)
  451. Xchar *str, *key;
  452. X/* Return the start (in s) of the next word (0 relative offest) if the
  453. X   key matches.  ``key'' must be in upper case. Otherwise return 0.
  454. X*/
  455. X{
  456. X   register char *s=str, *k=key;
  457. X   int c;
  458. X
  459. X   do {
  460. X      ++s, ++k;
  461. X      c = *s;
  462. X      if (islower(c)) c = toupper (c);
  463. X   } while (c == *k);
  464. X
  465. X   if (*k != '\0') return 0;
  466. X/*
  467. X   Now skip to the start of the next word;
  468. X*/
  469. X   while (*s && (*s == ' ' || *s == '\t')) ++s;
  470. X
  471. X   if (*s == '\0') return 0;
  472. X
  473. X   return s - str;  /* Offset of next word (to be bolded) */
  474. X}
  475. X
  476. XAddToTableOfContents(type)
  477. X{
  478. X   if( TocCount > TOC_SIZE )
  479. X      return;
  480. X   if( TocCount == TOC_SIZE )
  481. X   {
  482. X      fprintf(stderr, "%s: More than %d Table of contents entries; others ignored.\n",
  483. X      ProgName, TOC_SIZE);
  484. X      ++TocCount;
  485. X      return;
  486. X   }
  487. X
  488. X   if( type == NEWFILE )
  489. X      AddFile();
  490. X   else
  491. X      AddFunction();
  492. X}
  493. X
  494. XAddFunction()
  495. X{
  496. X   register int l;
  497. X   register char *p;
  498. X
  499. X   /* This heuristic stops multiple occurrences of a function,
  500. X         * selected by #ifdefs, to all end up many times over in the
  501. X         * Table of Contents.  One only needs to see it once.  -IAN!
  502. X         */
  503. X   if( TocCount > 0 && TocPages[TocCount-1] == PageNumber
  504. X      && strcmp(Toc[TocCount-1],FunctionName) == 0 )
  505. X      return;
  506. X   l = strlen(FunctionName);
  507. X   if( l >40 ) l = 40;
  508. X   p = Toc[TocCount] = (char *)malloc(l+1);
  509. X   strncpy(p, FunctionName, l);
  510. X   p[l] = '\0';
  511. X   TocPages[TocCount] = PageNumber;
  512. X   ++TocCount;
  513. X}
  514. X
  515. XAddFile()
  516. X{
  517. X   register int l;
  518. X   register int len;
  519. X   char temp[20];
  520. X#define MAXFNLEN 59+17  /* Room for 3 dots (...) */
  521. X
  522. X   len = strlen(Name) + 20;
  523. X   Toc[TocCount] = (char *)malloc(130);
  524. X   if (len > MAXFNLEN)
  525. X      sprintf(Toc[TocCount], "\n    File: ...%s ", &Name[len-MAXFNLEN-16]);
  526. X   else
  527. X      sprintf(Toc[TocCount], "\n    File: %s ", Name);
  528. X   l = strlen(Toc[TocCount]);
  529. X   if( l < 64 )
  530. X   {
  531. X      while( l < 64 )
  532. X         Toc[TocCount][l++] = ' ';
  533. X
  534. X      Toc[TocCount][l++] = '\0';
  535. X   }
  536. X   sprintf(temp, "  Page %4d\n", PageNumber);
  537. X   strcat(Toc[TocCount], temp);
  538. X   ++TocCount;
  539. X}
  540. X
  541. X#define MAXNAME    30
  542. XNewFile( reset )
  543. Xint reset;
  544. X{
  545. X   static first = 1;
  546. X   static char buf[45];
  547. X
  548. X   if( reset )
  549. X      first = 1;
  550. X   else
  551. X      GetFileTime();
  552. X
  553. X   if( strlen(Name) > MAXNAME ) {
  554. X      strcpy( buf, "... " );
  555. X      strcat( buf, Name+strlen(Name)-MAXNAME-4 );
  556. X      Title = buf;
  557. X   }
  558. X   else
  559. X      Title = Name;
  560. X
  561. X   if( ResetPage ) PageNumber=1;
  562. X
  563. X   switch( Printer ) {
  564. X      case POSTSCRIPT:
  565. X     if( !first && !ResetPage ) PageNumber++;
  566. X     if( !first ) puts( "endpage" );
  567. X     printf( "(%s) setdate\n", FileDate );
  568. X     printf( "(%s) newfile\n", Title );
  569. X     puts( "/sheet 1 def" );
  570. X     printf( "/pagenum %d def\n", PageNumber );
  571. X     puts( "startpage" );
  572. X     break;
  573. X
  574. X      default:
  575. X     if( first )
  576. X        PutHeader();
  577. X     else {
  578. X        BlankPage();
  579. X        if( StartOdd && (ActualPageCount % 2) != 0 ) BlankPage();
  580. X        if( !ResetPage ) PageNumber++;
  581. X        PutHeader();
  582. X     }
  583. X
  584. X     break;
  585. X   }
  586. X
  587. X   first = 0;
  588. X   AddToTableOfContents(NEWFILE);
  589. X   FileLineNumber = 0;
  590. X}
  591. X
  592. X
  593. XGetFileTime()
  594. X{
  595. X   struct stat st;
  596. X   extern char *ctime();
  597. X
  598. X   if( File == NULL ) return;
  599. X
  600. X   if( File == stdin )
  601. X      strncpy(FileDate, &Today[4], 20);
  602. X   else
  603. X      {
  604. X      fstat(fileno(File), &st);
  605. X      strncpy(FileDate, ctime((time_t *)&st.st_mtime) + 4, 20);
  606. X   }
  607. X   strncpy(&FileDate[12], &FileDate[15], 5);
  608. X   FileDate[17] = '\0';
  609. X}
  610. X
  611. XDumpTableOfContents()
  612. X{
  613. X   register int i, j;
  614. X   int index[TOC_SIZE];
  615. X   char buf[200];
  616. X
  617. X   if( TocCount == 0 ) return;
  618. X
  619. X   for (i = 0; i < TocCount; i++) index[i] = i;
  620. X   if( SortFlag )
  621. X      SortTable(index);
  622. X
  623. X   File = NULL;
  624. X   Name = "Table of Contents";
  625. X   FileDate = Today;
  626. X   ActualPageCount = 0;
  627. X   PageNumber = 1;
  628. X   LineNumber = 0;
  629. X   NewFile(1);
  630. X
  631. X   if( TitleFile != NULL )
  632. X   {
  633. X      FILE *f;
  634. X      char b[MAXLINE];
  635. X
  636. X      if( (f=fopen(TitleFile,"r")) == NULL ) {
  637. X         CANT_OPEN (TitleFile);
  638. X      }
  639. X      else
  640. X      {
  641. X         while( fgets(b, MAXLINE, f) != NULL )
  642. X         {
  643. X            if( strlen(b) ) b[strlen(b)-1]=0;
  644. X            PutString(b, -1, 0, 1);
  645. X            LineNumber++;
  646. X            if( ++LineNumber >= PageEnd ) NewPage();
  647. X         }
  648. X
  649. X         fclose(f);
  650. X      }
  651. X      NewPage();
  652. X   }
  653. X
  654. X   TocCount--; /* Bumped by NewFile for TOC */
  655. X   for( i=0; i < TocCount; ++i ) {
  656. X      char *s;
  657. X
  658. X      if( Toc[index[i]][0] == '\n' ) {
  659. X         if( (LineNumber + 5) >= PageEnd ) NewPage();
  660. X
  661. X     PutString("", -1, 0, 1);
  662. X     PutString(Toc[index[i]]+1, -1, 0, 1);
  663. X         LineNumber += 2;
  664. X         continue;
  665. X      }
  666. X      ++LineNumber;
  667. X      if( LineNumber >= PageEnd && (i+1) != TocCount ) NewPage();
  668. X
  669. X      sprintf(buf, "        %s ", Toc[index[i]]);
  670. X      s = buf+strlen(buf);
  671. X      for( j=strlen(Toc[index[i]]); j < 48; ++j ) *s++ = '.';
  672. X      *s++ = '\0';
  673. X      sprintf( buf, "%s %4d", buf, TocPages[index[i]]);
  674. X      PutString(buf, -1, 0, 1);
  675. X   }
  676. X
  677. X   if( Printer == POSTSCRIPT )
  678. X      puts( "endpage" );
  679. X   else {
  680. X      BlankPage();
  681. X      if( StartOdd && ((ActualPageCount % 2) != 0) ) BlankPage();
  682. X   }
  683. X}
  684. X
  685. XSortTable(index)
  686. Xregister int *index;
  687. X{
  688. X   register int i, temp, flag;
  689. X   char name1[MAXLINE];
  690. X   char name2[MAXLINE];
  691. X
  692. X   do {
  693. X      flag = 0;
  694. X      for (i = 0; i < TocCount - 1; i++)
  695. X      {
  696. X         if( Toc[index[i]][0] == '\n' || Toc[index[i+1]][0] == '\n' )
  697. X            continue; /* don't sort across file names */
  698. X         strcpy( name1, Toc[index[i]] );
  699. X         strcpy( name2, Toc[index[i+1]] );
  700. X
  701. X         if( CaseInsensitive )
  702. X         {
  703. X            char *p;
  704. X            char c;
  705. X            for(p = name1; c = *p; p++ )
  706. X               if( islower(c) ) *p=toupper(c);
  707. X            for(p = name2; c = *p; p++ )
  708. X               if( islower(c) ) *p=toupper(c);
  709. X         }
  710. X
  711. X         if( strcmp(name1, name2) > 0)
  712. X         {
  713. X            temp = index[i];
  714. X            index[i] = index[i+1];
  715. X            index[i+1] = temp;
  716. X            flag = 1;
  717. X         }
  718. X      }
  719. X   }
  720. X   while( flag );
  721. X}
  722. X
  723. Xenum langs WhichLanguage (file_name)
  724. Xchar *file_name;
  725. X/*
  726. X   Routine to return one of the enum languages based on the suffix of
  727. X   the file name.
  728. X*/
  729. X{
  730. X   char *end;
  731. X
  732. X   if (end = strrchr (file_name, '.')) {
  733. X      ++end;  /* Move past the '.' */
  734. X      switch (*end) {
  735. X      case 'C':    /* Allow .c, .C as suffixes (and ;231 for VMS, etc.) */
  736. X      case 'c':
  737. X      case 'Y':    /* And treat YACC as 'C' */
  738. X      case 'y':
  739. X         if (!isalpha(end[1]))
  740. X            return C;
  741. X      break;
  742. X      case 'F':     /* Allow .f, .F, .FOR, .for as suffixes */
  743. X      case 'f':
  744. X         if (!isalpha(end[1]))
  745. X            return FORTRAN;
  746. X
  747. X         if ((end[1] == 'o' || end[1] == 'O') &&
  748. X             (end[2] == 'r' || end[2] == 'R') && !isalpha(end[3]))
  749. X            return FORTRAN;
  750. X      break;
  751. X      case 'I':   /* Allow .icn or .ICN (or even .iCn) as suffixes */
  752. X      case 'i':
  753. X         if ((end[1] == 'c' || end[1] == 'C') &&
  754. X             (end[2] == 'n' || end[2] == 'N') && !isalpha(end[3]))
  755. X            return ICON;
  756. X      break;
  757. X      case 'L':   /* Allow both .lsp and .l */
  758. X      case 'l':
  759. X         if ((end[1] == 's' || end[1] == 'S') &&
  760. X             (end[2] == 'p' || end[2] == 'P') && !isalpha(end[3]))
  761. X            return LISP;
  762. X         if (!isalpha(end[1])) {
  763. X         /*
  764. X            Ok, we have .l for lisp or .l for lex (sigh).  To determine
  765. X            which, read in some lines and look for Lex '%'s or a "/*" or
  766. X            a bunch of lisp comments ';' or starting parens '('.
  767. X         */
  768. X            char buf[256], *ptr;
  769. X            int lcount=0, lisp = 0, lex = 0;
  770. X            while (fgets(buf, MAXLINE, File) != NULL) {
  771. X               ptr = buf;
  772. X               while (*ptr == ' ' || *ptr == '\t') ++ptr;
  773. X               if (*ptr == '\/') {
  774. X                  if (ptr[1] == '\*') {
  775. X                  /* Decisive, a line starts with a 'C' comment. */
  776. X                     lex = lisp + 1;
  777. X                     break;
  778. X                  }
  779. X                  else if (ptr[1] == '\/') {
  780. X                     ++lisp;  /* Lisp type comment seen (//) */
  781. X                  }
  782. X               }
  783. X               else if (*ptr == '%') {
  784. X               /* Decisive, lex requires '%'s to separate sections. */
  785. X                  lex = lisp + 1;
  786. X                  break;
  787. X               }
  788. X               else if (*ptr == '(' || *ptr == ';' || *ptr == '[') {
  789. X               /* Should be tons of these starting lines in lisp programs. */
  790. X                  if (++lisp > 4) {
  791. X                     lisp = lex + 1;
  792. X                     break;
  793. X                  }
  794. X               }
  795. X               if (++lcount > 50) {
  796. X               /* Give up. */
  797. X                  break;
  798. X               }
  799. X            }
  800. X         /* Rewind the file. */
  801. X            fseek (File, 0, 0);
  802. X            if (lisp > lex) return LISP;
  803. X            else return C;  /* Default to treat .l as lex code. */
  804. X         }
  805. X      /* Fall through */
  806. X      }
  807. X   }
  808. X   return NONE;
  809. X}
  810. X
  811. X
  812. XInit (pname)
  813. Xchar *pname;
  814. X/*
  815. X   Routine to select which printer is to be assumed.  Either the default
  816. X   (compiled in), or the environment variable CPRINTER, or the argument
  817. X   line choice.  Possible argument line or CPRINTER variables: "DUMB",
  818. X   "BACKSPACE", "ANSI", etc.  The passed in pointer ``printer'' is from
  819. X   the command line.
  820. X
  821. X   After printer has been selected, anything else that needs to be done
  822. X   to this printer (change pitch etc.) is done here.
  823. X*/
  824. X{
  825. X   char *cprinter, *getenv();
  826. X   char *psheader;
  827. X
  828. X   if ((cprinter = pname) != NULL || (cprinter = getenv("CPRINTER")) != NULL) {
  829. X   /* Figure out what this person wants to use as a cpr printer. */
  830. X      if (strcmp (cprinter, "DUMB") == 0)           Printer = DUMB;
  831. X      else if (strcmp (cprinter, "BACKSPACE") == 0) Printer = BACKSPACE;
  832. X      else if (strcmp (cprinter, "ANSI") == 0)      Printer = ANSI;
  833. X      else if (strcmp (cprinter, "LN03") == 0)      Printer = LN03;
  834. X      else if (strcmp (cprinter, "NECP5200") == 0)  Printer = NECP5200;
  835. X      else if (strcmp (cprinter, "POSTSCRIPT") == 0)Printer = POSTSCRIPT;
  836. X      else {
  837. X         fprintf (stderr, "Unknown printer %s\n", cprinter);
  838. X         exit(1);
  839. X      }
  840. X   }
  841. X   switch (Printer) {
  842. X      case POSTSCRIPT:
  843. X     PageEnd = PageLength;
  844. X     break;
  845. X
  846. X      case NECP5200:
  847. X      /* Setup the NEC P5200 (draft mode, 12 cpi, left margin) */
  848. X     printf ("\033x%c\033!%c\033l%c", 0, 1, 5);
  849. X     /*FALLTHROUGH*/
  850. X
  851. X      default:
  852. X     PageEnd = PageLength - ((PageLength > 30) ? 7 : 1);
  853. X   }
  854. X}
  855. X
  856. X
  857. XFini()
  858. X/*
  859. X   Undo whatever Init() did to the printer, etc.
  860. X*/
  861. X{
  862. X   switch (Printer) {
  863. X      case NECP5200:
  864. X     /* Reset to LQ mode, 10 cpi, left margin to 0 */
  865. X     printf ("\033x%c\033!%c\033l%c", 1, 0, 0);
  866. X     break;
  867. X
  868. X      case POSTSCRIPT:
  869. X     puts("endpage\n\n%%Trailer");
  870. X     puts("cleanup\ndocsave restore end\n");
  871. X     break;
  872. X   }
  873. X}
  874. X
  875. X
  876. XDumpPostscriptHeader()
  877. X{
  878. X   puts("%! a2ps 3.0");
  879. X   puts("");
  880. X   puts("/$a2psdict 100 dict def");
  881. X   puts("$a2psdict begin");
  882. X   puts("% Initialize page description variables.");
  883. X   puts("/inch {72 mul} bind def");
  884. X   puts("/landscape true def");
  885. X   puts("/twinpage true def");
  886. X   puts("/sheetheight 11.64 inch def");
  887. X   puts("/sheetwidth 8.27 inch def");
  888. X   puts("/margin 1.2 inch def");
  889. X   puts("/noborder false def");
  890. X   puts("/noheader false def");
  891. X   puts("/headersize 0.22 inch def");
  892. X   puts("/bodyfontsize 7.5 def");
  893. X   puts("/lines 66 def");
  894. X   puts("/columns 80 def");
  895. X   puts("/datewidth 0 def");
  896. X   puts("%!  PostScript Source Code");
  897. X   puts("%");
  898. X   puts("%  File: imag:/users/local/a2ps/header.ps");
  899. X   puts("%  Created: Tue Nov 29 12:14:02 1988 by miguel@imag (Miguel Santana)");
  900. X   puts("%  Version: 2.0");
  901. X   puts("%  Description: PostScript prolog for a2ps ascii to PostScript program.");
  902. X   puts("% ");
  903. X   puts("%  Edit History:");
  904. X   puts("%  - Original version by evan@csli (Evan Kirshenbaum).");
  905. X   puts("%  - Modified by miguel@imag to:");
  906. X   puts("%    1) Correct an overflow bug when printing page number 10 (operator");
  907. X   puts("%    cvs).");
  908. X   puts("%    2) Define two other variables (sheetwidth, sheetheight) describing");
  909. X   puts("%    the physical page (by default A4 format).");
  910. X   puts("%    3) Minor changes (reorganization, comments, etc).");
  911. X   puts("%  - Modified by tullemans@apolloway.prl.philips.nl");
  912. X   puts("%    1) Correct stack overflows with regard to operators cvs and copy.");
  913. X   puts("%       The resulting substrings where in some cases not popped off");
  914. X   puts("%       the stack, what can result in a stack overflow.");
  915. X   puts("%    2) Replaced copypage and erasepage by showpage. Page througput");
  916. X   puts("%       degrades severely (see red book page 140) on our ps-printer");
  917. X   puts("%       after printing sheet 16 (i.e. page 8) of a file which was ");
  918. X   puts("%       actually bigger. For this purpose the definitions of startdoc");
  919. X   puts("%       and startpage are changed.");
  920. X   puts("%  - Modified by Tim Clark <T.Clark@uk.ac.warwick> to:");
  921. X   puts("%    1) Print one page per sheet (portrait) as an option.");
  922. X   puts("%    2) Reduce size of file name heading, if it's too big.");
  923. X   puts("%    3) Save and restore PostScript state at begining/end. It now uses");
  924. X   puts("%    conventional %%Page %%Trailer markers.");
  925. X   puts("%    4) Print one wide page per sheet in landscape mode as an option.");
  926. X   puts("%  - Modified by miguel@imag.fr to");
  927. X   puts("%    1) Add new option to print n copies of a file.");
  928. X   puts("%    2) Add new option to suppress heading printing.");
  929. X   puts("%    3) Add new option to suppress page surrounding border printing.");
  930. X   puts("%    4) Add new option to change font size. Number of lines and columns");
  931. X   puts("%    are now automatically adjusted, depending on font size and");
  932. X   puts("%    printing mode used.");
  933. X   puts("%    5) Minor changes (best layout, usage message, etc).");
  934. X   puts("%");
  935. X   puts("");
  936. X   puts("% Copyright (c) 1988, Miguel Santana, miguel@imag.imag.fr");
  937. X   puts("%");
  938. X   puts("% Permission is granted to copy and distribute this file in modified");
  939. X   puts("% or unmodified form, for noncommercial use, provided (a) this copyright");
  940. X   puts("% notice is preserved, (b) no attempt is made to restrict redistribution");
  941. X   puts("% of this file, and (c) this file is not distributed as part of any");
  942. X   puts("% collection whose redistribution is restricted by a compilation copyright.");
  943. X   puts("%");
  944. X   puts("");
  945. X   puts("");
  946. X   puts("% General macros.");
  947. X   puts("/xdef {exch def} bind def");
  948. X   puts("/getfont {exch findfont exch scalefont} bind def");
  949. X   puts("");
  950. X   puts("% Page description variables and inch function are defined by a2ps program.");
  951. X   puts("");
  952. X   puts("% Character size for differents fonts.");
  953. X   puts("   landscape");
  954. X   puts("   { /filenamefontsize bodyfontsize 1.5 mul def }");
  955. X   puts("   { /filenamefontsize bodyfontsize 1.5 mul 16 def }");
  956. X   puts("ifelse");
  957. X   puts("/datefontsize filenamefontsize 0.6 mul def");
  958. X   puts("/headermargin filenamefontsize 0.25 mul def");
  959. X   puts("/bodymargin bodyfontsize 0.7 mul def");
  960. X   puts("");
  961. X   puts("% Font assignment to differents kinds of \"objects\"");
  962. X   puts("/filenamefontname /Helvetica-Bold def");
  963. X   puts("/stdfilenamefont filenamefontname filenamefontsize getfont def");
  964. X   puts("/datefont /Helvetica-Oblique datefontsize getfont def");
  965. X   puts("/bodyfont /Courier bodyfontsize getfont def");
  966. X   puts("/boldbodyfont /Courier-Bold bodyfontsize getfont def");
  967. X   puts("");
  968. X   puts("% Logical page attributes (a half of a real page or sheet).");
  969. X   puts("/pagewidth");
  970. X   puts("   bodyfont setfont (0) stringwidth pop columns mul bodymargin dup add add");
  971. X   puts("   def");
  972. X   puts("/pageheight");
  973. X   puts("   bodyfontsize lines mul bodymargin dup add add headersize add");
  974. X   puts("   def");
  975. X   puts("");
  976. X   puts("% Coordinates for upper corner of a logical page and for sheet number.");
  977. X   puts("% Coordinates depend on format mode used.");
  978. X   puts("% In twinpage mode, coordinate x of upper corner is not the same for left");
  979. X   puts("% and right pages: upperx is an array of two elements, indexed by sheetside.");
  980. X   puts("/rightmargin margin 4 div def");
  981. X   puts("/leftmargin margin 3 mul 4 div def");
  982. X   puts("/topmargin margin twinpage {3.6} {2} ifelse div def");
  983. X   puts("landscape");
  984. X   puts("{  % Landscape format");
  985. X   puts("   /uppery rightmargin pageheight add bodymargin add def");
  986. X   puts("   /sheetnumbery sheetwidth leftmargin pageheight add datefontsize add sub def");
  987. X   puts("   twinpage");
  988. X   puts("   {  % Two logical pages");
  989. X   puts("      /upperx [ topmargin            % upperx for left page");
  990. X   puts("        dup 2 mul pagewidth add        % upperx for right page");
  991. X   puts("          ] def");
  992. X   puts("      /sheetnumberx sheetheight topmargin sub def");
  993. X   puts("   }");
  994. X   puts("   {  /upperx [ topmargin dup ] def");
  995. X   puts("      /sheetnumberx sheetheight topmargin sub datefontsize sub def");
  996. X   puts("   }");
  997. X   puts("   ifelse");
  998. X   puts("}");
  999. X   puts("{  % Portrait format");
  1000. X   puts("   /uppery topmargin pageheight add def");
  1001. X   puts("   /upperx [ leftmargin dup ] def");
  1002. X   puts("   /sheetnumberx sheetwidth rightmargin sub datefontsize sub def");
  1003. X   puts("   /sheetnumbery");
  1004. X   puts("     sheetheight ");
  1005. X   puts("     topmargin pageheight add datefontsize add headermargin add");
  1006. X   puts("      sub");
  1007. X   puts("      def");
  1008. X   puts("");
  1009. X   puts("}");
  1010. X   puts("ifelse");
  1011. X   puts("");
  1012. X   puts("% Strings used to make easy printing numbers");
  1013. X   puts("/pnum 12 string def");
  1014. X   puts("/empty 12 string def");
  1015. X   puts("");
  1016. X   puts("% Other initializations.");
  1017. X   puts("/setdate");
  1018. X   puts("{" );
  1019. X   puts("/date exch def" );
  1020. X   puts("/datewidth date stringwidth pop def");
  1021. X   puts("filenameroom");
  1022. X   puts("} def\n");
  1023. X   puts("/filenameroom {");
  1024. X   puts("         pagewidth");
  1025. X   puts("     filenamefontsize 4 mul datewidth add (Page 9999) stringwidth pop add");
  1026. X   puts("      sub");
  1027. X   puts("   } def");
  1028. X   puts("");
  1029. X   puts("");
  1030. X   puts("% Function startdoc: initializes printer and global variables.");
  1031. X   puts("/startdoc");
  1032. X   puts("    { /sheetside 0 def            % sheet side that contains current page");
  1033. X   puts("      /sheet 1 def            % sheet number");
  1034. X   puts("   } bind def");
  1035. X   puts("");
  1036. X   puts("% Function newfile: init file name and reset page number for each new file.");
  1037. X   puts("/newfile");
  1038. X   puts("    { cleanup");
  1039. X   puts("      /filename xdef");
  1040. X   puts("      /filenamewidth filename stringwidth pop def");
  1041. X   puts("      /filenamefont");
  1042. X   puts("     filenamewidth filenameroom gt");
  1043. X   puts("     {");
  1044. X   puts("           filenamefontname");
  1045. X   puts("           filenamefontsize filenameroom mul filenamewidth div");
  1046. X   puts("        getfont");
  1047. X   puts("     }");
  1048. X   puts("     {  stdfilenamefont }");
  1049. X   puts("     ifelse");
  1050. X   puts("     def");
  1051. X   puts("    } bind def");
  1052. X   puts("");
  1053. X   puts("% Function printpage: Print a physical page.");
  1054. X   puts("/printpage");
  1055. X   puts("    { /sheetside 0 def");
  1056. X   puts("      twinpage");
  1057. X   puts("      {  noborder not");
  1058. X   puts("        { sheetnumber }");
  1059. X   puts("     if");
  1060. X   puts("      }");
  1061. X   puts("      {  noheader noborder not and");
  1062. X   puts("        { sheetnumber }");
  1063. X   puts("     if");
  1064. X   puts("      }");
  1065. X   puts("      ifelse");
  1066. X   puts("      showpage ");
  1067. X   puts("%      pagesave restore");
  1068. X   puts("      /sheet sheet 1 add def");
  1069. X   puts("    } bind def");
  1070. X   puts("");
  1071. X   puts("% Function cleanup: terminates printing, flushing last page if necessary.");
  1072. X   puts("/cleanup");
  1073. X   puts("    { twinpage sheetside 1 eq and");
  1074. X   puts("         { printpage }");
  1075. X   puts("      if");
  1076. X   puts("    } bind def");
  1077. X   puts("");
  1078. X   puts("% Function startpage: prints page header and page border and initializes");
  1079. X   puts("% printing of the file lines.");
  1080. X   puts("/startpage");
  1081. X   puts("    { sheetside 0 eq");
  1082. X   puts("    { % /pagesave save def");
  1083. X   puts("      landscape");
  1084. X   puts("        { sheetwidth 0 inch translate    % new coordinates system origin");
  1085. X   puts("          90 rotate                % landscape format");
  1086. X   puts("        } if");
  1087. X   puts("    } if");
  1088. X   puts("      noborder not { printborder } if");
  1089. X   puts("      noheader not { printheader } if");
  1090. X   puts("     upperx sheetside get  bodymargin  add");
  1091. X   puts("        uppery");
  1092. X   puts("        bodymargin bodyfontsize add  noheader {0} {headersize} ifelse add");
  1093. X   puts("     sub");
  1094. X   puts("      moveto");
  1095. X   puts("      bodyfont setfont");
  1096. X   puts("      gsave");
  1097. X   puts("    } bind def");
  1098. X   puts("");
  1099. X   puts("% Function printheader: prints page header.");
  1100. X   puts("/printheader");
  1101. X   puts("    { upperx sheetside get  uppery headersize sub 1 add  moveto");
  1102. X   puts("      datefont setfont");
  1103. X   puts("      gsave");
  1104. X   puts("        datefontsize headermargin rmoveto");
  1105. X   puts("    date show                    % date/hour");
  1106. X   puts("      grestore");
  1107. X   puts("      gsave");
  1108. X   puts("    pagenum pnum cvs pop");
  1109. X   puts("       pagewidth (Page 999) stringwidth pop sub");
  1110. X   puts("       headermargin");
  1111. X   puts("    rmoveto");
  1112. X   puts("        (Page ) show pnum show                % page number");
  1113. X   puts("      grestore");
  1114. X   puts("      empty pnum copy pop");
  1115. X   puts("      gsave");
  1116. X   puts("        filenamefont setfont");
  1117. X   puts("          filenameroom filename stringwidth pop sub 2 div datewidth add");
  1118. X   puts("          bodymargin 2 mul ");
  1119. X   puts("       add ");
  1120. X   puts("       headermargin");
  1121. X   puts("    rmoveto");
  1122. X   puts("        filename show                        % file name");
  1123. X   puts("      grestore");
  1124. X   puts("    } bind def");
  1125. X   puts("");
  1126. X   puts("% Function printborder: prints border page.");
  1127. X   puts("/printborder ");
  1128. X   puts("    { upperx sheetside get uppery moveto");
  1129. X   puts("      gsave                    % print the four sides");
  1130. X   puts("        pagewidth 0 rlineto            % of the square");
  1131. X   puts("        0 pageheight neg rlineto");
  1132. X   puts("        pagewidth neg 0 rlineto");
  1133. X   puts("        closepath stroke");
  1134. X   puts("      grestore");
  1135. X   puts("      noheader not");
  1136. X   puts("         { 0 headersize neg rmoveto pagewidth 0 rlineto stroke }");
  1137. X   puts("      if");
  1138. X   puts("    } bind def");
  1139. X   puts("");
  1140. X   puts("% Function endpage: adds a sheet number to the page (footnote) and prints");
  1141. X   puts("% the formatted page (physical impression). Activated at the end of each");
  1142. X   puts("% source page (lines reached or FF character).");
  1143. X   puts("/endpage {");
  1144. X   puts("     grestore");
  1145. X   puts("     /pagenum pagenum 1 add def");
  1146. X   puts("     twinpage  sheetside 0 eq  and");
  1147. X   puts("        { /sheetside 1 def }");
  1148. X   puts("        { printpage }");
  1149. X   puts("     ifelse");
  1150. X   puts("   } bind def");
  1151. X   puts("");
  1152. X   puts("% Function sheetnumber: prints the sheet number.");
  1153. X   puts("/sheetnumber");
  1154. X   puts("    { sheetnumberx sheetnumbery moveto");
  1155. X   puts("      datefont setfont");
  1156. X   puts("      sheet pnum cvs");
  1157. X   puts("     dup stringwidth pop (0) stringwidth pop sub neg 0 rmoveto show");
  1158. X   puts("      empty pnum copy pop");
  1159. X   puts("    } bind def");
  1160. X   puts("");
  1161. X   puts("% Function s: print a source line");
  1162. X   puts("/newline {");
  1163. X   puts("    grestore");
  1164. X   puts("    0 bodyfontsize neg rmoveto");
  1165. X   puts("    gsave");
  1166. X   puts("} bind def");
  1167. X   puts("/s  { show");
  1168. X   puts("      newline");
  1169. X   puts("    } bind def");
  1170. X   puts("/sb  {");
  1171. X   puts("        boldbodyfont setfont");
  1172. X   puts("        show");
  1173. X   puts("     bodyfont setfont");
  1174. X   puts("    } bind def");
  1175. X   puts("/sn  {");
  1176. X   puts("        show");
  1177. X   puts("    } bind def");
  1178. X   puts("%%EndProlog");
  1179. X   puts("\n\n/docsave save def\nstartdoc\n");
  1180. X}
  1181. END_OF_FILE
  1182. if test 32782 -ne `wc -c <'cpr.c2'`; then
  1183.     echo shar: \"'cpr.c2'\" unpacked with wrong size!
  1184. fi
  1185. # end of 'cpr.c2'
  1186. fi
  1187. echo shar: End of archive 3 \(of 5\).
  1188. cp /dev/null ark3isdone
  1189. MISSING=""
  1190. for I in 1 2 3 4 5 ; do
  1191.     if test ! -f ark${I}isdone ; then
  1192.     MISSING="${MISSING} ${I}"
  1193.     fi
  1194. done
  1195. if test "${MISSING}" = "" ; then
  1196.     echo You have unpacked all 5 archives.
  1197.     rm -f ark[1-9]isdone
  1198. else
  1199.     echo You still need to unpack the following archives:
  1200.     echo "        " ${MISSING}
  1201. fi
  1202. ##  End of shell archive.
  1203. exit 0
  1204.  
  1205.